#include "timeout_kick.h"

// 获取当前时间（毫秒）
timestamp_t get_current_time() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (timestamp_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}

// 初始化时间轮
void timewheel_init(TimeWheel* tw) {
    // 清空时间轮结构内存
    memset(tw, 0, sizeof(TimeWheel));
    // 设置当前槽位为0
    tw->current_slot = 0;
    // 记录时间轮启动时间
    tw->start_time = get_current_time();
    // 设置时间获取函数
    tw->get_time_func = get_current_time;
    
    // 初始化所有槽位的链表为空
    for (int i = 0; i < TIME_WHEEL_SIZE; i++) {
        tw->slots[i].head = NULL;
        tw->slots[i].tail = NULL;
    }
    
    // 初始化连接映射表，所有连接ID对应的节点指针设为NULL
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        tw->connections[i] = NULL;
    }
    
    // 打印初始化信息
    printf("时间轮初始化完成，总槽数: %d, 超时时间: %d秒\n", 
           TIME_WHEEL_SIZE, TIMEOUT_SECONDS);
}

// 添加连接到时间轮
void timewheel_add_connection(TimeWheel* tw, int netfd) {
    // 检查连接ID有效性
    if (netfd < 0 || netfd >= MAX_CONNECTIONS) {
        printf("错误: 无效的连接ID %d\n", netfd);
        return;
    }
    
    // 检查连接是否已存在
    if (tw->connections[netfd] != NULL) {
        printf("错误: 连接ID %d 已存在\n", netfd);
        return;
    }
    
    // 分配新节点内存
    node_lt* node = (node_lt*)malloc(sizeof(node_lt));
    if (!node) {
        printf("错误: 内存分配失败，无法添加连接 %d\n", netfd);
        return;
    }
    
    // 初始化节点信息
    node->netfd = netfd;
    node->last_activate = tw->get_time_func();
    node->prev = NULL;
    node->next = NULL;
    node->slot_idx = tw->current_slot; // 记录当前槽位索引
    
    // 获取当前槽位
    TimeWheelSlot* slot = &tw->slots[tw->current_slot];
    
    // 将节点添加到当前槽位的链表尾部
    if (!slot->head) {
        // 链表为空时，头和尾都指向新节点
        slot->head = slot->tail = node;
    } else {
        // 链表不为空时，将新节点添加到尾部
        slot->tail->next = node;
        node->prev = slot->tail;
        slot->tail = node;
    }
    
    // 更新连接映射表
    tw->connections[netfd] = node;
    printf("连接 %d 已添加到时间轮，当前槽位: %d\n", netfd, tw->current_slot);
}

// 激活连接（更新活跃时间）
void timewheel_activate_connection(TimeWheel* tw, int netfd) {
    // 检查连接ID有效性
    if (netfd < 0 || netfd >= MAX_CONNECTIONS) {
        printf("错误: 无效的连接ID %d\n", netfd);
        return;
    }
    
    // 获取连接对应的节点
    node_lt* node = tw->connections[netfd];
    if (!node) {
        printf("错误: 连接ID %d 不存在\n", netfd);
        return;
    }
    
    // 通过node->slot_idx直接定位原槽位，无需遍历
    TimeWheelSlot* old_slot = &tw->slots[node->slot_idx];
    
    // 从原槽位的链表中移除节点
    if (old_slot->head == node) {
        old_slot->head = node->next;
    }
    if (old_slot->tail == node) {
        old_slot->tail = node->prev;
    }
    if (node->prev) {
        node->prev->next = node->next;
    }
    if (node->next) {
        node->next->prev = node->prev;
    }
    
    // 更新时间并添加到当前槽位
    node->last_activate = tw->get_time_func();
    node->slot_idx = tw->current_slot; // 更新槽位索引为当前槽位
    TimeWheelSlot* new_slot = &tw->slots[tw->current_slot];
    
    // 将节点添加到新槽位的链表尾部
    if (!new_slot->head) {
        new_slot->head = new_slot->tail = node;
        node->prev = node->next = NULL;
    } else {
        new_slot->tail->next = node;
        node->prev = new_slot->tail;
        node->next = NULL;
        new_slot->tail = node;
    }
    
    printf("连接 %d 已激活，移动到槽位 %d\n", netfd, tw->current_slot);
}

// 移除连接
void timewheel_remove_connection(TimeWheel* tw, int netfd) {
    // 检查连接ID有效性
    if (netfd < 0 || netfd >= MAX_CONNECTIONS) {
        printf("错误: 无效的连接ID %d\n", netfd);
        return;
    }
    
    // 获取连接对应的节点
    node_lt* node = tw->connections[netfd];
    if (!node) {
        printf("警告: 连接ID %d 不存在，无法移除\n", netfd);
        return;
    }
    
    // 通过node->slot_idx直接定位所在槽位
    TimeWheelSlot* slot = &tw->slots[node->slot_idx];
    
    // 从槽位链表中删除节点
    if (slot->head == node) {
        // 节点是头节点时，更新头指针
        slot->head = node->next;
        if (slot->head) {
            slot->head->prev = NULL;
        } else {
            slot->tail = NULL; // 链表为空时同步更新尾指针
        }
    } else if (slot->tail == node) {
        // 节点是尾节点时，更新尾指针
        slot->tail = node->prev;
        if (slot->tail) {
            slot->tail->next = NULL;
        } else {
            slot->head = NULL; // 链表为空时同步更新头指针
        }
    } else {
        // 节点在链表中间时，调整前后节点的指针
        if (node->prev) {
            node->prev->next = node->next;
        }
        if (node->next) {
            node->next->prev = node->prev;
        }
    }
    
    // 从连接映射表中移除
    tw->connections[netfd] = NULL;
    // 释放节点内存
    free(node);
    
    printf("连接 %d 已从时间轮移除\n", netfd);
}

// 时间轮向前滚动一个槽位
void timewheel_tick(TimeWheel* tw, int *remove_netfd) {
    *remove_netfd = -1;
    // 保存旧槽位索引
    int old_slot = tw->current_slot;
    // 更新当前槽位索引（循环滚动）
    tw->current_slot = (tw->current_slot + 1) % TIME_WHEEL_SIZE;
    // 获取当前时间
    timestamp_t current_time = tw->get_time_func();

    // 转换当前时间戳为可读时间字符串
    time_t now = time(NULL);
    char* time_str = ctime(&now);
    time_str[strcspn(time_str, "\n")] = 0;  // 移除换行符

    printf("时间轮 tick，从槽位 %d 移动到槽位 %d\n", old_slot, tw->current_slot);

    // 检查旧槽位中的所有连接是否超时
    TimeWheelSlot* slot = &tw->slots[old_slot];
    node_lt* current = slot->head;

    while (current) {
        // 提前保存next指针，避免节点被释放后失效
        node_lt* next = current->next;
        // 计算连接空闲时间（秒）
        timestamp_t idle_time = (current_time - current->last_activate) / 1000;

        if (idle_time >= TIMEOUT_SECONDS) {
            // 打印被踢出的时间和原因（超时30秒）
            printf("[%s] 连接%d被踢出（超时30秒）\n",
                   time_str, current->netfd);
            printf("连接 %d 超时（空闲时间: %.2f秒 > %d秒），即将关闭\n",
                   current->netfd, (double)idle_time, TIMEOUT_SECONDS);
            // 移除超时连接
            *remove_netfd = current->netfd;
            timewheel_remove_connection(tw, current->netfd);
        }

        current = next;
    }
}

// 清理时间轮资源
void timewheel_cleanup(TimeWheel* tw) {
    // 移除所有连接
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        if (tw->connections[i]) {
            timewheel_remove_connection(tw, i);
        }
    }
    
    printf("时间轮资源已清理\n");
}


// 打印当前时间的函数
void print_current_time() {
    time_t now = time(NULL);
    char* time_str = ctime(&now);
    // 移除换行符
    time_str[strcspn(time_str, "\n")] = 0;
    printf("时间: %s | ", time_str);
}

// 打印所有活跃连接的函数
void print_active_connections(TimeWheel* tw) {
    printf("活跃连接: ");
    int has_active = 0;
    
    // 遍历所有可能的连接ID
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        if (tw->connections[i] != NULL) {
            printf("%d ", i);
            has_active = 1;
        }
    }
    
    if (!has_active) {
        printf("无");
    }
    printf("\n");
}
